package
{
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	public class World
	{
		public static const SHOW_QUADTREE_DEBUG:Boolean = false;
		public static const WORLD_DENSITY:int = 500;
		public var size:Point;
		public var display:Sprite;
		public var pathingDebugDisplay:Sprite;
		
		private var m_bots:Vector.<Bot>;
		//private var m_obstacles:Vector.<WorldObject>;
		private var m_obstacles:ISpatialIndex;
		
		private var m_quadDisplay:Sprite;
		
		public var obstacleLayer:Sprite;
		public var quadLayer:Sprite;

		public function World()
		{
			m_bots = new Vector.<Bot>;
			
			quadLayer = new Sprite();
			obstacleLayer = new Sprite();
			display = new Sprite();
			display.addChild(quadLayer);
			display.addChild(obstacleLayer);
			
			pathingDebugDisplay = new Sprite();
			display.addChild(pathingDebugDisplay);
			m_quadDisplay = new Sprite();
			
		}
		
		public function getRect():Rectangle{
			return new Rectangle(0,0,size.x, size.y);
		}
		
		public function initialize():void{
			var grid:Sprite = Util.getGrid(size, Global.PPU);
			grid.visible = false;
			display.addChild(grid);
			m_obstacles = new QuadTreeSpatialIndex(size);
			//m_obstacles = new ListSpatialIndex();
			quadLayer.addChild(m_quadDisplay);
			
		}
		
		public function getCollisions(rect:Rectangle):Vector.<ISpatialIndexable>{
			var collisions:Vector.<ISpatialIndexable> = m_obstacles.getRectCollisions(rect) as Vector.<ISpatialIndexable>;
			return collisions;
		}
		
		public function getCollisionsByPoint(point:Point):Vector.<ISpatialIndexable>{
			var collisions:Vector.<ISpatialIndexable> = m_obstacles.getPointCollisions(point) as Vector.<ISpatialIndexable>;
			return collisions;						
		}
		
		public function generateRandomObstacle():void{
			var i:int = 0;
			var blockSize:int = 6;			
			var collisions:Vector.<ISpatialIndexable>;
			var worldObject:WorldObject = new WorldObject();
			var height:int = Global.PRNG.nextIntRange(1,blockSize);
			var width:int = Global.PRNG.nextIntRange(1,blockSize);
			var x:int = Global.PRNG.nextIntRange(0,size.x);
			var y:int = Global.PRNG.nextIntRange(0,size.y);
			var obstacleAdded:Boolean = false;
			worldObject.size = new Point(width, height);
			worldObject.location = new Point(x,y);
			
			if(getRect().containsRect(worldObject.getRect())){
				collisions = getCollisions(worldObject.getRect());
				if(collisions.length == 0){
					worldObject.initialize();
					addObstacle(worldObject);
					obstacleAdded = true;
				}
			}			
			
			if(SHOW_QUADTREE_DEBUG){
				var parent:DisplayObjectContainer = m_quadDisplay.parent;
				m_quadDisplay.parent.removeChild(m_quadDisplay);
				m_quadDisplay = (m_obstacles as QuadTreeSpatialIndex).getDisplay();
				parent.addChild(m_quadDisplay);
			}
			
		}
		
		public function generateRandomObstacles():void{
			var i:int = 0;
			Global.PRNG.seed = 34;
			while(i++ < WORLD_DENSITY){
				generateRandomObstacle();
			}
		}
		
		public function addObstacle(obs:WorldObject):void{
			m_obstacles.add(obs);
			obstacleLayer.addChild(obs.display);
		}
		
		public function addBot(vision:Number):void{
			var bot:Bot = new Bot();
			bot.currentPosition = new Point(0,0);
			bot.world = this;
			bot.vision = vision;
			bot.parentDisplay = display;
			bot.initialize();
			
			m_bots.push(bot);
		}
		
		public function update():void{
			var i:int, il:int;
			for(i = 0, il = m_bots.length; i < il; i++){
				m_bots[i].update();
			}
		}
	}
}